
#include "CPU_const.h"

typedef unsigned int   uint;

//void EncryptionCycle(uint *pBhi, uint *pAlo);


uint const TabSub[16]=  { 0xFFFFFFFF,
                          0xEEEEEEEE,
                          0xDDDDDDDD,
                          0xCCCCCCCC,
                          0xBBBBBBBB,
                          0xAAAAAAAA,
                          0x99999999,
                          0x88888888,
                          0x77777777,
                          0x66666666,
                          0x55555555,
                          0x44444444,
                          0x33333333,
                          0x22222222,
                          0x11111111,
                          0x00000000  };

uint const Key[8]=  { 0x12345678,
                      0x9ABCDEF0,
                      0x0FEDCBA9,
                      0x87654321,
                      0x01234567,
                      0x89ABCDEF,
                      0x0FE67899,
                      0x7847374D  };






void GOST28147::INITgen(uint *pBhi, uint *pAlo)
{ /*EncryptionCycle(pBhi,pAlo);*/ BhiGen = *pBhi; AloGen = *pAlo; }
  



//void GOST28147::TACTgen(void)
void GOST28147::TACTgen(uint *pBhi, uint *pAlo)
{
  if(BhiGen>BiMAX) BhiGen -= MOD32_1;     AloGen += C1gen; BhiGen += C2gen;
  EncryptionCycle(&BhiGen,&AloGen);
  *pBhi = BhiGen; *pAlo = AloGen;
}



void GOST28147::XORgen(uint *pDataHi, uint *pDataLo)  { *pDataHi ^= BhiGen; *pDataLo ^= AloGen; }





void GOST28147::EncryptionCycle(uint *pBhi, uint *pAlo)
{ 
  ForwardCycle(pAlo,pBhi); ForwardCycle(pAlo,pBhi); ForwardCycle(pAlo,pBhi); BackCycle(pAlo,pBhi);
  swap(pAlo,pBhi);
}

void GOST28147::DecryptionCycle(uint *pBhi, uint *pAlo)
{ 
  ForwardCycle(pAlo,pBhi); BackCycle(pAlo,pBhi); BackCycle(pAlo,pBhi); BackCycle(pAlo,pBhi);
  swap(pAlo,pBhi);
}

void GOST28147::AuthenticationCycle(uint *pN1, uint *pN2)
{ ForwardCycle(pN1,pN2); ForwardCycle(pN1,pN2); ForwardCycle(pN1,pN2); BackCycle(pN1,pN2); }





void GOST28147::ForwardCycle(uint *pN1, uint *pN2)
{ int cycle;    for(cycle=0; cycle<8; ++cycle) {MainStep(pN1,pN2,Key[cycle]);}  }

void GOST28147::BackCycle(uint *pN1, uint *pN2)
{ int cycle;    for(cycle=7; cycle>-1; --cycle) {MainStep(pN1,pN2,Key[cycle]);} }


void GOST28147::MainStep(uint *pN1, uint *pN2, uint X)
{ uint S;
  S = TablChanging(*pN1 + X);   S = ((S<<11)|(S>>21))^*pN2;    *pN2 = *pN1;    *pN1 = S; 
}





uint GOST28147::TablChanging(uint valIn)
{  uint cycle, valOut=0, msk = 0x0000000F;
//
  for(cycle=0; cycle<8; ++cycle)
   { valOut |= TabSub[(valIn&msk)>>cycle*4]&msk;  msk <<= 4; }
//
  return valOut;
}


void GOST28147::swap(uint *pA, uint *pB)   { uint C = *pA; *pA = *pB; *pB = C; }